package edu.po.au.server.service;

import edu.po.au.server.EPConstants;
import edu.po.au.server.PMF;
import edu.po.au.server.domain.AuctionHead;
import edu.po.au.server.domain.Product;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.api.server.spi.response.CollectionResponse;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.datanucleus.query.JDOCursorHelper;

import java.util.HashMap;
import java.util.List;

import javax.annotation.Nullable;
import javax.inject.Named;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

@Api(name = "au", version = EPConstants.API_VERSION, clientIds = {
		com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID,
		EPConstants.WEB_CLIENT_ID }, audiences = { EPConstants.ANDROID_AUDIENCE }, scopes = { "https://www.googleapis.com/auth/userinfo.email" })
public class AuctionEndpoint {

	@SuppressWarnings({ "unchecked", "unused" })
  @ApiMethod(name = "auction.list.bycategroy", path="auction/list/bycategory/{categoryname}")
	public CollectionResponse<AuctionHead> listAuctionHeadByCat(@Named("categoryname") String categoryName,
			@Nullable @Named("cursor") String cursorString,
			@Nullable @Named("limit") Integer limit) {

		PersistenceManager mgr = null;
		Cursor cursor = null;
		List<AuctionHead> execute = null;
		Product product = null;
		try {
			mgr = getPersistenceManager();
			Query query = mgr.newQuery(AuctionHead.class);
			
			if (cursorString != null && cursorString != "") {
				cursor = Cursor.fromWebSafeString(cursorString);
				HashMap<String, Object> extensionMap = new HashMap<String, Object>();
				extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
				query.setExtensions(extensionMap);
			}

			if (limit != null) {
				query.setRange(0, limit);
			}

			if (categoryName != null) {
				query.setFilter(AuctionHead.CATEGORY_Name + "=='"+categoryName+"'");
			}
			
			execute = (List<AuctionHead>) query.execute();
			cursor = JDOCursorHelper.getCursor(execute);
			if (cursor != null)
				cursorString = cursor.toWebSafeString();

			// Tight loop for fetching all entities from datastore and accomodate
			// for lazy fetch.
			for (AuctionHead obj : execute)
				;
		} finally {
			mgr.close();
		}

		return CollectionResponse.<AuctionHead> builder().setItems(execute).setNextPageToken(cursorString).build();
	}

	@SuppressWarnings({ "unchecked", "unused" })
  @ApiMethod(name = "auction.list.byproduct", path="auction/list/byproduct/{producttext}")
	public CollectionResponse<AuctionHead> listAuctionHeadByPro(@Named("producttext") String productText,
			@Nullable @Named("cursor") String cursorString,
			@Nullable @Named("limit") Integer limit) {

		PersistenceManager mgr = null;
		Cursor cursor = null;
		List<AuctionHead> execute = null;
		Product product = null;
		try {
			mgr = getPersistenceManager();
			Query query = mgr.newQuery(AuctionHead.class);
			query.setFilter(product.PRODUCT_TEXT + ".contains('"+productText+"')");
			if (cursorString != null && cursorString != "") {
				cursor = Cursor.fromWebSafeString(cursorString);
				HashMap<String, Object> extensionMap = new HashMap<String, Object>();
				extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
				query.setExtensions(extensionMap);
			}

			if (limit != null) {
				query.setRange(0, limit);
			}

			execute = (List<AuctionHead>) query.execute();
			cursor = JDOCursorHelper.getCursor(execute);
			if (cursor != null)
				cursorString = cursor.toWebSafeString();

			// Tight loop for fetching all entities from datastore and accomodate
			// for lazy fetch.
			for (AuctionHead obj : execute)
				;
		} finally {
			mgr.close();
		}

		return CollectionResponse.<AuctionHead> builder().setItems(execute).setNextPageToken(cursorString).build();
	}
	
	@ApiMethod(name = "auction.get", path="auction/get")
	public AuctionHead getAuctionHead(@Named("id") Long id) {
		PersistenceManager mgr = getPersistenceManager();
		AuctionHead auction = null;
		try {
			auction = mgr.getObjectById(AuctionHead.class, id);
		} finally {
			mgr.close();
		}
		return auction;
	}

	@ApiMethod(name = "auction.insert", path="auction/insert")
	public AuctionHead insertAuctionHead(AuctionHead auction) {
		PersistenceManager mgr = getPersistenceManager();
		try {
			if (containsAuctionHead(auction)) {
				throw new EntityExistsException("Object already exists");
			}
			mgr.makePersistent(auction);
		} finally {
			mgr.close();
		}
		return auction;
	}

	@ApiMethod(name = "auction.update", path="auction/update")
	public AuctionHead updateAuctionHead(AuctionHead auction) {
		PersistenceManager mgr = getPersistenceManager();
		try {
			if (!containsAuctionHead(auction)) {
				throw new EntityNotFoundException("Object does not exist");
			}
			mgr.makePersistent(auction);
		} finally {
			mgr.close();
		}
		return auction;
	}

	@ApiMethod(name = "auction.remove", path="auction/remove")
	public void removeAuctionHead(@Named("id") Long id) {
		PersistenceManager mgr = getPersistenceManager();
		try {
			AuctionHead auction = mgr.getObjectById(AuctionHead.class, id);
			mgr.deletePersistent(auction);
		} finally {
			mgr.close();
		}
	}

	private boolean containsAuctionHead(AuctionHead auction) {
		PersistenceManager mgr = getPersistenceManager();
		boolean contains = true;
		try {
			mgr.getObjectById(AuctionHead.class, auction.getId());
		} catch (javax.jdo.JDOObjectNotFoundException ex) {
			contains = false;
		} finally {
			mgr.close();
		}
		return contains;
	}

	private static PersistenceManager getPersistenceManager() {
		return PMF.get().getPersistenceManager();
	}

}
